[IA64] fix RSE issues rlated to handle_lazy_cover().
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Fri, 23 Jun 2006 21:24:06 +0000 (15:24 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Fri, 23 Jun 2006 21:24:06 +0000 (15:24 -0600)
It must be after trying vTLB in ia64_do_page_fault().

This patch fixes the following scenario.

linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S
Here psr.i and psr.ic is off
rse_clear_invalid:
...
(pRecurse) br.call.dptk.few b0=rse_clear_invalid
        ;;
        mov loc8=0
        mov loc9=0

1. Right before mov loc8=0, vcpu is switched to another cpu.
2. While the vcpu is waiting for cpu, the tlb entry which backs the rse
   stack is purged.
3. The vcpu gets cpu again, tlb miss fault occurs with isr.ir = 1.
4. xen ia64_do_page_fault() calls handle_lazy_cover() which sets
   cr.ifs = 0.
5. xen returns cpu execution to the guest.
6. mov loc8 = 0 is executed with cfm = 0.
   Illigal operation fault is raised
7. priv_handle_op() is called. but it fails to emulate because
   mov loc8 = 0 isn't privileged op.
8. ia64_handle_privop() calls panic_domain().

Signed-off-by: Xu, Anthony <anthony.xu@intel.com>
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
xen/arch/ia64/xen/faults.c

index 5c2981dbab6f8081aab60031a298e619c171f863..ac16d3a32e6067c4f9e4eab2264254f153b61fc2 100644 (file)
@@ -218,7 +218,6 @@ void ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_reg
        int is_ptc_l_needed = 0;
        u64 logps;
 
-       if ((isr & IA64_ISR_IR) && handle_lazy_cover(current, regs)) return;
        if ((isr & IA64_ISR_SP)
            || ((isr & IA64_ISR_NA) && (isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH))
        {
@@ -269,6 +268,10 @@ void ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_reg
                }
                return;
        }
+
+       if ((isr & IA64_ISR_IR) && handle_lazy_cover(current, regs))
+               return;
+
        if (!PSCB(current,interrupt_collection_enabled)) {
                check_bad_nested_interruption(isr,regs,fault);
                //printf("Delivering NESTED DATA TLB fault\n");